package com.idreems.imagesns.ui;

import java.io.IOException;
import java.util.List;

import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Address;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.SearchRecentSuggestions;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.TextView;
import android.widget.Toast;

import com.amap.api.search.core.AMapException;
import com.amap.api.search.geocoder.Geocoder;
import com.androidquery.AQuery;
import com.costum.android.widget.PullAndLoadListView;
import com.google.gson.Gson;
import com.idreems.imagesns.Consts;
import com.idreems.imagesns.R;
import com.idreems.imagesns.WeiboApplication;
import com.idreems.imagesns.adapters.StatusItemAdapter;
import com.idreems.imagesns.model.Statuses;
import com.idreems.imagesns.model.WeiboObject;
import com.idreems.imagesns.util.Constants;
import com.idreems.imagesns.util.Preferences;
import com.idreems.imagesns.util.Util;
import com.weibo.sdk.android.Oauth2AccessToken;
import com.weibo.sdk.android.WeiboException;
import com.weibo.sdk.android.api.PlaceAPI;
import com.weibo.sdk.android.api.WeiboAPI.SORT3;
import com.weibo.sdk.android.net.RequestListener;

/**
 * 用给定的坐标数据实现逆地理编码，并将得到的地名用Toast打印在地图上
 */
public class LocationWeiboActivity extends FragmentActivity
{
	private static final String TAG = "LocationWeiboActivity";
	private static final int FIRST_PAGE = 1;
	private static final int DEFAULT_DISTANCE = 1000;
	Oauth2AccessToken mAccessToken;

	private StatusItemAdapter mAdapter = null;
	private PullAndLoadListView mListView = null;

	private AQuery aq;

	private int mCurrentPage = FIRST_PAGE;
	private int mCurrentDistance = DEFAULT_DISTANCE;
	private long mLatesttime = 0;

	private ProgressDialog progDialog = null;
	private Geocoder coder;
	private float mLat;
	private float mLong;
	private boolean mLocated;
	private TextView searchTextView;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.location_weibo);
		mAccessToken = ((WeiboApplication) getApplication()).getOauth2AccessToken();
		if (hasAccessToken())
		{
			initView();
		}
		else
		{
			Intent intent = new Intent(this, AuthenticatedActivity.class);
			startActivity(intent);
		}
	}

	private void reset()
	{
		mLocated = false;
		setLatestTime(0);
	}
	// 地理编码
	public void getLatlon(final String name)
	{
		reset();
		Thread t = new Thread(new Runnable()
		{
			public void run()
			{
				try
				{
					List<Address> address = coder.getFromLocationName(name, 3);
					if (address != null && address.size() > 0)
					{
						Address addres = address.get(0);
						mLong = (float) addres.getLongitude();
						mLat = (float) addres.getLatitude();
						mLocated = true;
						Log.d(TAG, "getLatitude:"+mLat+" getLongitude:"+mLong);
						handler.sendMessage(Message.obtain(handler, Constants.REOCODER_RESULT));
					}
				}
				catch (AMapException e)
				{
					handler.sendMessage(Message.obtain(handler, Constants.ERROR));
				}

			}
		});

		progDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		progDialog.setIndeterminate(false);
		progDialog.setCancelable(true);
		progDialog.setMessage("正在获取地址");
		progDialog.show();
		t.start();
	}

	protected void doSearchQuery(Intent intent)
	{
		String query = intent.getStringExtra(SearchManager.QUERY);
		SearchRecentSuggestions suggestions = new SearchRecentSuggestions(LocationWeiboActivity.this, MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
		suggestions.saveRecentQuery(query, null);
		searchTextView.setText(query);

		getLatlon(query);
	}

	@Override
	protected void onNewIntent(final Intent newIntent)
	{
		super.onNewIntent(newIntent);
		String ac = newIntent.getAction();
		if (Intent.ACTION_SEARCH.equals(ac))
		{
			doSearchQuery(newIntent);
		}
	}

	private Handler handler = new Handler()
	{
		public void handleMessage(Message msg)
		{
			if (msg.what == Constants.REOCODER_RESULT)
			{
				progDialog.dismiss();
				nearbyStatus(FIRST_PAGE, getCurrentDistance());
				// Toast.makeText(getApplicationContext(), addressName, Toast.LENGTH_SHORT).show();
			}
			else if (msg.what == Constants.ERROR)
			{
				progDialog.dismiss();
				Toast.makeText(getApplicationContext(), "请检查网络连接是否正确?", Toast.LENGTH_SHORT).show();
			}
		}
	};

	private void nearbyPhotosRefresh(final float lat, final float lon, final int page, int distance)
	{
		android.util.Log.d(TAG, "page: " + page);
		PlaceAPI statusAPI = new PlaceAPI(mAccessToken);
		statusAPI.nearbyPhotos(String.valueOf(lat), String.valueOf(lon), distance, getLatestTime(), getEndTime(), SORT3.SORT_BY_TIME, 50, page, false, new RequestListener()
		{
			@Override
			public void onComplete(String result)
			{
				WeiboObject response = null;
				try
				{
					Gson gson = new Gson();
					response = gson.fromJson(result, WeiboObject.class);
				}
				catch (Exception e)
				{
				}
				if (response == null || response != null && response.statuses == null)
				{
					runOnUiThread(new Runnable()
					{

						@Override
						public void run()
						{
							Util.showToast(LocationWeiboActivity.this, getString(R.string.no_new_blog_toast));
							hideLoadingIndicator();

							setLastSyncTime(Util.getNowLocaleTime());
							// Call onRefreshComplete when the list has been refreshed.
							mListView.onRefreshComplete();
							mListView.setLastUpdated(getLastSyncTime(Preferences.PREF_LAST_SYNC_TIME));
						}
					});
					return;
				}
				if (response != null && response.statuses != null)
				{

					// update latest time
					if (getCurrentPage() == FIRST_PAGE)
					{
						try
						{
							setLatestTime(Util.parseDate(response.statuses.get(0).created_at).getTime());
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}

					android.util.Log.d(TAG, String.format("+%d/%d", response.statuses.size(), response.total_number));
				}
				mAdapter.addNewestStatuses(response.statuses);
				final int count = response.statuses.size();
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						hideLoadingIndicator();
						aq.id(R.id.placeholder_error).gone();

						showContents();
						setLastSyncTime(Util.getNowLocaleTime());
						// Call onRefreshComplete when the list has been refreshed.
						mListView.onRefreshComplete();
						mListView.setLastUpdated(getLastSyncTime(Preferences.PREF_LAST_SYNC_TIME));

						mAdapter.notifyDataSetChanged();
						Util.showToast(LocationWeiboActivity.this, String.format(getString(R.string.new_blog_toast), count));
					}
				});
			}

			@Override
			public void onError(final WeiboException e)
			{
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						showErrorIndicator();
						aq.id(R.id.error_msg).text(e.getMessage());
						aq.id(R.id.retry_button).clicked(new OnClickListener()
						{

							@Override
							public void onClick(View v)
							{
								nearbyStatus(getCurrentPage(), getCurrentDistance());
							}
						});
					}
				});
			}

			@Override
			public void onIOException(final IOException e)
			{
			}

		});
	}

	private void nearbyPhotosLoadMore(final float lat, final float lon, final int page, int distance)
	{
		android.util.Log.d(TAG, "page: " + page);
		PlaceAPI statusAPI = new PlaceAPI(mAccessToken);
		statusAPI.nearbyPhotos(String.valueOf(lat), String.valueOf(lon), distance, 0, 0, SORT3.SORT_BY_TIME, 50, page, false, new RequestListener()
		{
			@Override
			public void onComplete(String result)
			{
				WeiboObject response = null;
				try
				{
					Gson gson = new Gson();
					response = gson.fromJson(result, WeiboObject.class);
				}
				catch (Exception e)
				{
				}
				if (response == null || response != null && response.statuses == null)
				{
					runOnUiThread(new Runnable()
					{

						@Override
						public void run()
						{
							Util.showToast(LocationWeiboActivity.this, getString(R.string.no_old_blog_toast));
							hideLoadingIndicator();

							mListView.onLoadMoreComplete();
						}
					});
					return;
				}
				if (response != null && response.statuses != null)
				{
					android.util.Log.d(TAG, String.format("+%d/%d", response.statuses.size(), response.total_number));
				}

				mAdapter.addStatuses(response.statuses);
				final int count = response.statuses.size();
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						hideLoadingIndicator();
						aq.id(R.id.placeholder_error).gone();

						mAdapter.notifyDataSetChanged();
						mListView.onLoadMoreComplete();

						Util.showToast(LocationWeiboActivity.this, String.format(getString(R.string.old_blog_toast), count));
					}
				});
			}

			@Override
			public void onError(final WeiboException e)
			{
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						displayToast("Error:" + e.getMessage());
						// Notify the loading more operation has finished
						// TODO: remove the OnLoadMoreListener of the listview as
						// there has error or no more items to load.
						mListView.onLoadMoreComplete();
					}
				});
			}

			@Override
			public void onIOException(final IOException e)
			{
				runOnUiThread(new Runnable()
				{

					@Override
					public void run()
					{
						displayToast("Error:" + e.getMessage());
						mListView.onLoadMoreComplete();
					}
				});
			}

		});
	}

	private void setCurrentPage(int page)
	{
		mCurrentPage = page;
	}

	private int getCurrentPage()
	{
		return mCurrentPage;
	}

	private void setCurrentDistance(int distance)
	{
		mCurrentDistance = distance;
	}

	private int getCurrentDistance()
	{
		return mCurrentDistance;
	}

	public void loadMoreData(final int page, final int distance)
	{
		if (!mLocated)
		{
			return;
		}
		hideErrorIndicator();
		showLoadingIndicator();

		setCurrentPage(page);
		setCurrentDistance(distance);

		nearbyPhotosLoadMore(mLat, mLong, page, distance);
	}

	public void nearbyStatus(final int page, final int distance)
	{
		if (!mLocated)
		{
			return;
		}
		hideErrorIndicator();
		showLoadingIndicator();

		setCurrentPage(page);
		setCurrentDistance(distance);
		
		nearbyPhotosRefresh(mLat, mLong, page, distance);
	}

	private void showLoadingIndicator()
	{
		aq.id(R.id.placeholder_loading).visible();
	}

	private void hideLoadingIndicator()
	{
		aq.id(R.id.placeholder_loading).gone();
	}

	private void showErrorIndicator()
	{
		aq.id(R.id.placeholder_error).visible();
	}

	private void hideErrorIndicator()
	{
		aq.id(R.id.placeholder_error).gone();
	}

	private String getLastSyncTime(String pre)
	{
		SharedPreferences prefs = Preferences.get(this);
		String time = prefs.getString(pre, "");
		return time;
	}

	private void setLastSyncTime(String time)
	{
		SharedPreferences.Editor editor = Preferences.get(this).edit();
		editor.putString(Preferences.PREF_LAST_SYNC_TIME, time);
		editor.commit();
	}

	private void showContents()
	{
		aq.id(R.id.timelist_list).visible();

		// FIXME: put it here, else will pop up "Tap to Refresh"
		mListView.setAdapter(mAdapter);
	}

	private void setLatestTime(long time)
	{
		android.util.Log.d(TAG, "setLatestTime: " + time);
		mLatesttime = time;
	}

	private long getLatestTime()
	{
		android.util.Log.d(TAG, "getLatestTime: " + mLatesttime);
		return mLatesttime;
	}

	private long getEndTime()
	{
		long r = mLatesttime != 0 ? System.currentTimeMillis() : 0;
		android.util.Log.d(TAG, "getEndTime: " + r);
		return r;
	}

	private void initView()
	{
		aq = new AQuery(this);

		mListView = ((PullAndLoadListView) findViewById(R.id.msg_list_item));

		// Set a listener to be invoked when the list should be refreshed.
		mListView.setOnRefreshListener(new PullAndLoadListView.OnRefreshListener()
		{
			@Override
			public void onRefresh()
			{
				nearbyStatus(FIRST_PAGE, getCurrentDistance());
			}
		});

		mListView.setOnLoadMoreListener(new PullAndLoadListView.OnLoadMoreListener()
		{

			public void onLoadMore()
			{
				loadMoreData(getCurrentPage() + 1, getCurrentDistance());
			}
		});

		mListView.setLastUpdated(getLastSyncTime(Preferences.PREF_LAST_SYNC_TIME));

		mAdapter = new StatusItemAdapter(this);

		// nearbyStatus(FIRST_PAGE, getCurrentDistance());

		mListView.setOnItemClickListener(new OnItemClickListener()
		{
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id)
			{

				// see: How to determine onItemClick for pulltorefreshlistview
				// http://stackoverflow.com/questions/10959030/how-to-determine-onitemclick-for-pulltorefreshlistview
				Statuses status = (Statuses) mListView.getItemAtPosition(position);

				if (status == null)
				{
					return;
				}
				else
				{
					Bundle bundle = new Bundle();
					bundle.putSerializable(Consts.STATUSES_KEY, status);

					Intent intent = new Intent(LocationWeiboActivity.this, StatusDetailActivity.class);
					intent.putExtras(bundle);
					startActivity(intent);
				}
			}
		});

		coder = new Geocoder(this);
		searchTextView = (TextView) findViewById(R.id.TextViewSearch);
		searchTextView.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				onSearchRequested();
			}

		});
		progDialog = new ProgressDialog(this);
	}

	private boolean hasAccessToken()
	{
		SharedPreferences prefs = Preferences.get(this);
		String token = prefs.getString(Preferences.ACCESS_TOKEN, null);
		String expires_in = String.valueOf(prefs.getLong(Preferences.EXPIRES_IN, 0));

		return (token != null && expires_in != null);
	}

	public static Intent createIntent(Context context)
	{
		Intent intent = new Intent(context, TimelineActivity.class);
		return intent;
	}

	/**
	 * @param resId
	 */
	public void displayToast(int resId)
	{
		Toast.makeText(this, resId, Toast.LENGTH_SHORT).show();
	}

	/**
	 * @param text
	 */
	public void displayToast(CharSequence text)
	{
		Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
	}
}